import { _decorator, Component, Node, Prefab, randomRangeInt, Label, Animation } from 'cc';
import { AudioMain } from '../audio/AudioMain';
import { Bullet } from '../bullet/Bullet';
import { BulletProp } from '../bullet/BulletProp';
import { EnemyPlane } from '../plane/EnemyPlane';
import { SelfPlane } from '../plane/SelfPlane';
import { BulletPropType, Combination, DifficultyMode, Direction, EnemyType, GameState } from './Enum';
import { PoolManager } from './PoolManager';
const { ccclass, property } = _decorator;

@ccclass('GameManager')
export class GameManager extends Component {
    // 玩家飞机
    @property(SelfPlane)
    public playerPlane: SelfPlane = null

    // 不同类型子弹预设
    @property(Prefab)
    public bullet01: Prefab = null
    @property(Prefab)
    public bullet02: Prefab = null
    @property(Prefab)
    public bullet03: Prefab = null
    @property(Prefab)
    public bullet04: Prefab = null
    @property(Prefab)
    public bullet05: Prefab = null
    // 不同敌方飞机预设
    @property(Prefab)
    public enemy01: Prefab = null
    @property(Prefab)
    public enemy02: Prefab = null
    // 不同道具预设
    @property(Prefab)
    public bulletPropM: Prefab = null
    @property(Prefab)
    public bulletPropH: Prefab = null
    @property(Prefab)
    public bulletPropS: Prefab = null
    // 游戏中分数文本
    @property(Label)
    public gameScore: Label = null
    // 游戏结束分数文本
    @property(Label)
    public gameOverScore: Label = null
    // 游戏结束动画
    @property(Animation)
    public gameOverAnim: Animation = null
    // 游戏中UI
    @property(Node)
    public gameing: Node = null
    // 游戏结束UI
    @property(Node)
    public gameOver: Node = null
    // 游戏音频管理
    @property(AudioMain)
    public audioMain: AudioMain = null
    // 道具速度
    @property
    public bulletPropSpeed = 3
    // 不同敌机速度
    @property
    public enemy01Speed = 5
    @property
    public enemy02Speed = 7

    // 子弹的管理节点
    @property(Node)
    public bulletRoot: Node = null

    // 子弹速度
    @property
    public bulletSpeed = 10
    // 子弹发射周期
    @property
    public shootTimeOut = 0.3

    // 敌机生成周期
    @property
    public createEnemyTimeOut = 5

    // 用于记录射击时间(当前时间超过子弹发射周期时发射下一枚)
    private _currShootTime = 0
    // 子弹是否射击
    private _isShooting = false
    // 用于记录敌机生成时间(当前时间超过)
    private _currCreateEnemyTime = 0
    // 游戏难度
    private _difficultyMode = 0
    // 游戏总分
    private _score = 0
    // 当前游戏状态
    private _gameState = GameState.START
    // 玩家子弹类型
    private _bulletType = BulletPropType.BULLET_M

    start() {
        this._init()
    }

    update(deltaTime: number) {
        // 判断是否在游戏中
        if (!this.isInGame()) return

        // 判断玩家是否死亡
        if (this.playerPlane.isDie) {
            this.setGameState(GameState.OVER)
            this.audioMain.play('playerDie')
            return
        }

        // 玩家飞机射击逻辑
        this._currShootTime += deltaTime
        if (this._isShooting && this._currShootTime > this.shootTimeOut) {
            this.playerShoot()
            this._currShootTime = 0
        }

        // 敌机生成逻辑
        this._currCreateEnemyTime += deltaTime
        switch (this._difficultyMode) {
            case DifficultyMode.TYPE01:
                // 难度1,随机位置生成一个随机敌机
                if (this._isShooting && this._currCreateEnemyTime > this.createEnemyTimeOut) {
                    this.createEnemyPlane()
                    this._currCreateEnemyTime = 0
                }
                break;
            case DifficultyMode.TYPE02:
                // 难度2
                if (this._isShooting && this._currCreateEnemyTime > 0.9 * this.createEnemyTimeOut) {
                    const rangeCombination = randomRangeInt(0, 2)
                    if (rangeCombination === Combination.TYPE02) {
                        // 组合2
                        this.createCombination1()
                    } else {
                        // 组合1
                        this.createEnemyPlane()
                    }
                    this._currCreateEnemyTime = 0
                }
                break;
            case DifficultyMode.TYPE03:
                // 难度3
                if (this._isShooting && this._currCreateEnemyTime > 0.8 * this.createEnemyTimeOut) {
                    const rangeCombination = randomRangeInt(0, 3)
                    if (rangeCombination === Combination.TYPE03) {
                        // 组合3
                        this.createCombination2()
                    } else if (rangeCombination === Combination.TYPE02) {
                        // 组合2
                        this.createCombination1()
                    } {
                        // 组合1
                        this.createEnemyPlane()
                    }
                    this._currCreateEnemyTime = 0
                }
                break;
            default:
                // 难度4
                if (this._isShooting && this._currCreateEnemyTime > 0.8 * this.createEnemyTimeOut) {
                    const rangeCombination = randomRangeInt(0, 3)
                    if (rangeCombination === Combination.TYPE03) {
                        // 组合3
                        this.createCombination2()
                    } else if (rangeCombination === Combination.TYPE02) {
                        // 组合2
                        this.createCombination1()
                    } {
                        // 组合1
                        this.createEnemyPlane()
                    }
                    this._currCreateEnemyTime = 0
                }
                break;
        }
    }

    // 初始化
    private _init() {
        this._currShootTime = this.shootTimeOut
    }

    // 设置是否射击
    public setIsShooting(value: boolean) {
        if (value === this._isShooting) return
        this._isShooting = value
    }
    // 发射子弹
    public playerShoot() {
        // 玩家飞机位置
        const pos = this.playerPlane.node.position
        // 子弹数组
        let bullets: Node[] = []
        // 判断当前子弹类型
        switch (this._bulletType) {
            case BulletPropType.BULLET_H:
                // H型子弹，两发
                // 实例化子弹预制，两个子弹3
                bullets = new Array<Node>(2).fill(null).map(() => PoolManager.instantiate().getNode(this.bullet03, this.bulletRoot))
                bullets.forEach((bullet, index) => {
                    // 设置子弹的初始位置
                    bullet.setPosition(pos.x - 2.5 + index * 5, pos.y, pos.z - 7)
                    // 设置子弹速度和方向
                    const bulletComp = bullet.getComponent(Bullet)
                    bulletComp.bulletSpeed = this.bulletSpeed
                })
                break;
            case BulletPropType.BULLET_S:
                // S型子弹，三发
                // 实例化子弹预制，三个子弹5
                bullets = new Array<Node>(3).fill(null).map(() => PoolManager.instantiate().getNode(this.bullet05, this.bulletRoot))
                bullets.forEach((bullet, index) => {
                    // 设置子弹的初始位置
                    bullet.setPosition(pos.x - 4 + index * 4, pos.y, pos.z - 7)
                    // 设置子弹速度和方向
                    const bulletComp = bullet.getComponent(Bullet)
                    bulletComp.bulletSpeed = this.bulletSpeed
                    if (index === 0) {
                        bulletComp.direction = Direction.LEFT
                    } else if (index === 2) {
                        bulletComp.direction = Direction.RIGHT
                    } else {
                        bulletComp.direction = Direction.MIDDLE
                    }
                })
                break;
            default:
                // M型子弹，一发
                // 实例化子弹预制，子弹1
                bullets = [PoolManager.instantiate().getNode(this.bullet01, this.bulletRoot)]
                // 设置子弹的初始位置
                bullets[0].setPosition(pos.x, pos.y, pos.z - 7)
                // 设置子弹速度和方向
                const bulletComp = bullets[0].getComponent(Bullet)
                bulletComp.bulletSpeed = this.bulletSpeed
        }
        this.audioMain.bulletEffectPlay(this._bulletType)
    }
    // 随机位置生成随机一架敌机
    public createEnemyPlane() {
        // 随机敌机类型
        const enemyType = randomRangeInt(0, 2)
        // 敌机预设
        let prefab: Prefab = null
        // 敌机速度
        let enemySpeed = 0
        if (enemyType === EnemyType.TYPE01) {
            // 类型1
            prefab = this.enemy01
            enemySpeed = this.enemy01Speed
        } else {
            // 类型2
            prefab = this.enemy02
            enemySpeed = this.enemy02Speed
        }
        // 生成敌机节点
        const enemy = PoolManager.instantiate().getNode(prefab, this.node)
        // 设置敌机速度
        const enemyComp = enemy.getComponent(EnemyPlane)
        enemyComp.enemySpeed = enemySpeed
        // 随机生成坐标
        const enemyPosX = randomRangeInt(-20, 21)
        enemy.setPosition(enemyPosX, 0, -45)
        // 设置敌机发射子弹
        enemyComp.setBullet(true, this.bullet02, 10, this)
    }
    // 组合2，生成五架飞机
    public createCombination1() {
        const enemyArr = new Array<Node>(5).fill(null).map(() => PoolManager.instantiate().getNode(this.enemy01, this.node))
        enemyArr.forEach((item, index) => {
            item.setPosition(-20 + index * 10, 0, -50)
            const enemyComp = item.getComponent(EnemyPlane)
            enemyComp.enemySpeed = this.enemy01Speed
            enemyComp.setGameManager(this)
        })
    }
    // 组合3，生成七架飞机v字形排列
    public createCombination2() {
        const enemyArr = new Array<Node>(7).fill(null).map(() => PoolManager.instantiate().getNode(this.enemy02, this.node))
        enemyArr.forEach((item, index) => {
            item.setPosition(-18 + index * 6, 0, -45 - Math.abs(index - 3) * 5)
            const enemyComp = item.getComponent(EnemyPlane)
            enemyComp.enemySpeed = this.enemy02Speed
            enemyComp.setGameManager(this)
        })
    }
    // 改变游戏难度
    public changePlaneMode() {
        this.schedule(this._modeChange, 20, 3)
        this.createBulletProp()
    }
    // 回调函数
    private _modeChange() {
        if (this._difficultyMode < 3) this._difficultyMode++
        this.createBulletProp()
    }

    // 加分
    public addScore(num: number) {
        this._score += num
        // 游戏中分数文本
        this.gameScore.string = this._score.toString()
        // 游戏结束分数文本
        this.gameOverScore.string = this._score.toString()
    }

    // 改变玩家子弹类型
    public changeBulletType(type: BulletPropType) {
        this._bulletType = type
    }

    // 生成子弹类型切换道具
    public createBulletProp() {
        const randomProp = randomRangeInt(0, 3)
        let prefab: Prefab = null
        if (randomProp === BulletPropType.BULLET_H) {
            prefab = this.bulletPropH
        } else if (randomProp === BulletPropType.BULLET_S) {
            prefab = this.bulletPropS
        } else {
            prefab = this.bulletPropM
        }
        const prop = PoolManager.instantiate().getNode(prefab, this.node)
        prop.setPosition(15, 0, -50)
        const propComp = prop.getComponent(BulletProp)
        propComp.setPropSpeed(this, this.bulletPropSpeed, this.bulletPropSpeed)
    }

    // 是否是游戏中状态
    public isInGame() {
        return this._gameState === GameState.INGAME
    }
    // 是否是开始游戏状态
    public isGameStart() {
        return this._gameState === GameState.START
    }
    // 设置游戏状态
    public setGameState(state: GameState) {
        if (this._gameState === GameState.OVER) this.resetData()
        if (state === GameState.INGAME) {
            this.setIsShooting(true)
            this.changePlaneMode()
            this.playerPlane.initLife()
        } else if (state === GameState.OVER) {
            // 子弹是否射击
            this._isShooting = false
            // 取消游戏难度定时器
            this.unschedule(this._modeChange)
            // 销毁场景中所有的对象
            // this.node.destroyAllChildren()
            let length = this.node.children.length
            for (let i = length - 1; i >= 0; i--) {
                PoolManager.instantiate().putNode(this.node.children[i])
            }
            // 销毁场景中所有的子弹
            // this.bulletRoot.destroyAllChildren()
            length = this.bulletRoot.children.length
            for (let i = length - 1; i >= 0; i--) {
                PoolManager.instantiate().putNode(this.bulletRoot.children[i])
            }
            this.gameing.active = false
            this.gameOver.active = true
            this.gameOverAnim.play()
        }
        this._gameState = state
    }
    // 重置游戏数据
    public resetData() {
        // 用于记录射击时间(当前时间超过子弹发射周期时发射下一枚)
        this._currShootTime = 0
        // 用于记录敌机生成时间(当前时间超过)
        this._currCreateEnemyTime = 0
        // 游戏难度
        this._difficultyMode = 0
        // 游戏总分
        this._score = 0
        // 玩家子弹类型
        this._bulletType = BulletPropType.BULLET_M
        // 玩家飞机位置
        this.playerPlane.node.setPosition(0, 0, 15)
        // 游戏中分数文本
        this.gameScore.string = '0'
        // 游戏结束分数文本
        this.gameOverScore.string = '0'
    }
}

